/*
	File:	std/ptr.hpp
	Date:	2013-06-01
	Author:	Asteroth
*/


#ifndef __ZEN_PTR_HPP__
#define __ZEN_PTR_HPP__

#include <boost/shared_ptr.hpp>
#include <boost/shared_array.hpp>

#define ptr(type) boost::shared_ptr<type>
#define arr(type) boost::shared_array<type>


/*
#include "mem.hpp"

#define ptr(type) std::SmartPointer<type, std::detail::PointerTypeOps<valueType> >
#define arr(type) std::SmartPointer<type, std::detail::ArrayTypeOps<valueType> >

namespace std {

	/**
	 * This class implements managed pointer via reference counting, it aims to be simpler and faster than boost implementations.
	 * /
	template <typename valueType, typename ptrTypeOps> class SmartPointer;

	namespace detail {

		template <typename valueType> class PointerTypeOps;
		template <typename valueType> class ArrayTypeOps;

	}

	//template <typename valueType> typedef SmartPointer<valueType, detail::PointerTypeOps<valueType> > SmartPtr;
	//template <typename valueType> typedef SmartPointer<valueType, detail::ArrayTypeOps<valueType> > SmartArray;
	
	
	template <typename valueType, typename ptrTypeOps>
	class SmartPointer {

	public:

		typedef SmartPointer<valueType, ptrTypeOps> SmartPointerType;
		typedef SmartAllocator<valueType> Allocator;

		/**
		 * Null constructor.
		 * This will not reference anything.
		 * /
		SmartPointer();

		/**
		 * Pointer constructor.
		 * This will reference the passed raw pointer.
		 * /
		SmartPointer(valueType* pointer);

		/**
		 * Copy constructor.
		 * This will reference the other pointer's reference.
		 * /
		SmartPointer(const SmartPointerType &copy);

		/**
		 * Destructor will delete the referenced pointer if it's reference counter reaches 0.
		 * /
		~SmartPointer();

		/**
		 * This will reference the other pointer's reference.
		 * /
		SmartPointerType& operator = (const SmartPointerType &copy);

		/**
		 * This will reference the passed raw pointer, it must not be deleted manually afterward.
		 * /
		SmartPointerType& operator = (valueType* pointer);

		/**
		 * Tells whether this references a null pointer.
		 * /
		bool null() const;

		/**
		 * Return the referenced raw pointer, it must not be deleted manually afterward.
		 * /
		valueType* get() const;

		/**
		 * Sets the reference to the passed raw pointer, it must not be deleted manually afterward.
		 * /
		void set(valueType* pointer);

		/**
		 * Sets this pointer to null.
		 * /
		void reset();


	private:
	
		struct reference {
			size_t count;
			valueType* pointer;
		} *ref;

	};

	
	template <typename valueType, typename ptrTypeOps>
	SmartPointer<valueType, ptrTypeOps>::SmartPointer() {
		ref = nullptr;
	}
	
	template <typename valueType, typename ptrTypeOps>
	SmartPointer<valueType, ptrTypeOps>::SmartPointer(valueType* pointer) {
		if (pointer) {
			ref = new reference;
			ref->count = 1;
			ref->pointer = pointer;
		} else {
			ref = nullptr;
		}
	}
	
	template <typename valueType, typename ptrTypeOps>
	SmartPointer<valueType, ptrTypeOps>::SmartPointer(const SmartPointer<valueType, ptrTypeOps> &copy) {
		ref = copy.ref;
		if (ref)
			ref->count++;
	}
	
	template <typename valueType, typename ptrTypeOps>
	SmartPointer<valueType, ptrTypeOps>::~SmartPointer() {
		reset();
	}
	
	template <typename valueType, typename ptrTypeOps>
	inline SmartPointer<valueType, ptrTypeOps>& SmartPointer<valueType, ptrTypeOps>::operator = (const SmartPointer<valueType, ptrTypeOps> &copy) {
		reset();
		if (copy.ref) {
			ref = copy.ref;
			ref->count++;
		}
		return *this;
	}
	
	template <typename valueType, typename ptrTypeOps>
	inline SmartPointer<valueType, ptrTypeOps>& SmartPointer<valueType, ptrTypeOps>::operator = (valueType* pointer) {
		set(pointer);
		return *this;
	}
	
	template <typename valueType, typename ptrTypeOps>
	inline bool SmartPointer<valueType, ptrTypeOps>::null() const {
		return ref == nullptr || ref->pointer == nullptr;
	}
	
	template <typename valueType, typename ptrTypeOps>
	inline valueType* SmartPointer<valueType, ptrTypeOps>::get() const {
		return ref == nullptr ? nullptr : ref->pointer;
	}
	
	template <typename valueType, typename ptrTypeOps>
	inline void SmartPointer<valueType, ptrTypeOps>::set(valueType* pointer) {
		reset();
		if (pointer) {
			ref = new reference;
			ref->count = 1;
			ref->pointer = pointer;
		}
	}
	
	template <typename valueType, typename ptrTypeOps>
	inline void SmartPointer<valueType, ptrTypeOps>::reset() {
		if (ref) {
			ref->count--;
			if (ref->count == 0) {
				if (ref->pointer != nullptr)
					deleter(ref->pointer);
				delete ref;
			}
		}
		ref = nullptr;
	}


	namespace detail {

		template <typename valueType>
		class PointerTypeOps {
		public:
			PointerTypeOps(valueType* pointer) {
				delete pointer;
			}
		};

		template <typename valueType>
		class ArrayTypeOps {
		public:
			ArrayTypeOps(valueType* pointer) {
				SmartAllocator<valueType>::freeArray(pointer);
			}
			ArrayTypeOps(valueType** pointer) {
				SmartAllocator<valueType>::freeArray(pointer);
			}
			ArrayTypeOps(valueType*** pointer) {
				SmartAllocator<valueType>::freeArray(pointer);
			}
			ArrayTypeOps(valueType*** pointer) {
				SmartAllocator<valueType>::freeArray(pointer);
			}
			ArrayTypeOps(valueType**** pointer) {
				SmartAllocator<valueType>::freeArray(pointer);
			}
			ArrayTypeOps(valueType***** pointer) {
				SmartAllocator<valueType>::freeArray(pointer);
			}
			ArrayTypeOps(valueType****** pointer) {
				SmartAllocator<valueType>::freeArray(pointer);
			}
		};

	} // namespace detail
	

	template <typename valueType>
	inline valueType* SmartPointer<valueType, detail::PointerTypeOps<valueType> >::operator -> () {
		return ref->pointer;
	}

	template <typename valueType>
	inline valueType& SmartPointer<valueType, detail::PointerTypeOps<valueType> >::operator * () {
		return *ref->pointer;
	}

	template <typename valueType>
	inline valueType& SmartPointer<valueType, detail::ArrayTypeOps<valueType> >::operator [] (unsigned int index) {
		return *ptr.get()[index];
	}


	template <typename valueType>
	static inline SmartPointer<valueType, detail::ArrayTypeOps<valueType> >& SmartPointer<valueType, detail::ArrayOps<valueType> >::allocArray(unsigned int size0) {
		SmartPointer<valueType, detail::Array1dOps<valueType> > ptr(SmartAllocator<valueType>::allocArray(size0));
		return ptr;
	}

	template <typename valueType>
	static inline SmartPointer<valueType, detail::ArrayTypeOps<valueType> >& SmartPointer<valueType, detail::ArrayOps<valueType> >::allocArray(unsigned int size0, unsigned int size1) {
		SmartPointer<valueType*, detail::Array2dOps<valueType*> > ptr(SmartAllocator<valueType>::allocArray(size0, size1));
		return ptr;
	}

	template <typename valueType>
	static inline SmartPointer<valueType, detail::ArrayTypeOps<valueType> >& SmartPointer<valueType, detail::ArrayOps<valueType> >::allocArray(unsigned int size0, unsigned int size1, unsigned int size2) {
		SmartPointer<valueType**, detail::Array3dOps<valueType**> > ptr(SmartAllocator<valueType>::allocArray(size0, size1, size2));
		return ptr;
	}

	template <typename valueType>
	static inline SmartPointer<valueType, detail::ArrayTypeOps<valueType> >& SmartPointer<valueType, detail::ArrayOps<valueType> >::allocArray(unsigned int size0, unsigned int size1, unsigned int size2, unsigned int size3) {
		SmartPointer<valueType**, detail::Array3dOps<valueType**> > ptr(SmartAllocator<valueType>::allocArray(size0, size1, size2));
		return ptr;
	}

	template <typename valueType>
	static inline SmartPointer<valueType, detail::ArrayTypeOps<valueType> >& SmartPointer<valueType, detail::ArrayOps<valueType> >::allocArray(unsigned int size0, unsigned int size1, unsigned int size2, unsigned int size3, unsigned int size4) {
		SmartPointer<valueType**, detail::Array3dOps<valueType**> > ptr(SmartAllocator<valueType>::allocArray(size0, size1, size2));
		return ptr;
	}


	template <typename valueType>
	typedef SmartPointer<valueType, detail::PointerTypeOps<valueType> > SharedPointer;

	template <typename valueType>
	typedef SmartPointer<valueType, detail::ArrayTypeOps<valueType> > SharedArray;

} // namespace std
*/


#endif // __ZEN_PTR_HPP__